import {Websock} from './websock'
import {xMessager} from './xMessager'
import {ChatDisplay} from './chatDisplay'
import {xchat_swf_message} from './xchat_swf_message'
import store from '@/store'
function xchat_swf_error(Error,xmessager){
	console.log("swf_error: " + Error);
	xmessager.SocketError();
}
/*
Array.prototype.push8 = function (num) {
    this.push(num & 0xFF);
};

Array.prototype.push16 = function (num) {
    this.push((num >> 8) & 0xFF,
              (num     ) & 0xFF  );
};

Array.prototype.pushStr = function (str) {
	var n = str.length;
	for (var i=0; i < n; i++) {
		this.push(str.charCodeAt(i));
	}
};
*/

function push8(array,num) {
    array.push(num & 0xFF);
}

function push16(array,num) {
    array.push((num >> 8) & 0xFF,(num) & 0xFF  );
}

function pushStr(array,str) {
	var n = str.length;
	for (var i=0; i < n; i++) {
		array.push(str.charCodeAt(i));
	}
}

const PACKET_HEARTBEAT = 			1;
const PACKET_REENTER  =	 			100;
const PACKET_ROOM_REINIT  =	 		101;
const PACKET_LOGIN  = 				110;
const PACKET_LOGIN_ACK  = 			111;
const PACKET_SESSION_PARAM  = 		112;
const PACKET_LOGOUT  = 				113;
const PACKET_KICKOUT  = 			114;
const PACKET_ROOMCLEAR  = 			115;
const PACKET_ROOMHOT  = 			116;

const PACKET_SOMEBODY_IN  = 		120;
const PACKET_SOMEBODY_OUT  = 		121;
const PACKET_SOMEBODY_CHANGELEVEL = 122;
const PACKET_SOMEBODY_CHANGEAPPDATA=123;
const PACKET_SOMEBODY_CHATENABLE  = 124;

const PACKET_CHAT  = 				125;

const PACKET_TOKEN_NUMBER  =		140;
const PACKET_TOKEN_INFO  = 			141;
const PACKET_TOKEN_OP  = 			142;
const PACKET_TOKEN_OP_EX  =			143;
const PACKET_TOKEN_SETTING  = 		144;
const PACKET_TOKEN_TIMER  = 		145;	

var xchat_protocol = {
	packet_fetch_state:0,
	packet_header:[],
	packet_type:0,
	packet_para:0,
	packet_body:[],
	packet_body_length:0,
	member_in_out_hint:0,
	Closed_By_Server:0,
	SessionID:0,
	logined:false,
	passport:'0',
	
	parse_header : function(){
		if (this.packet_header.length==4){
			this.packet_body_length = (this.packet_header[0]<<8)+this.packet_header[1];
			console.log('parse_header,packet_body_length,'+this.packet_body_length);
			this.packet_type = this.packet_header[2];
			this.packet_para = this.packet_header[3];
		}
		else{
			throw("xchat_protocol packet header error.");
		}
	},

	process_packet : function(xmessager){
		if (this.packet_type!=1){
			return;
		}
			
		if (this.packet_para == PACKET_HEARTBEAT){
			return;
		}

		var message_type;
		var packet_object;
		
		var temp = String.fromCharCode.apply(null,this.packet_body);
		
		try{
			packet_object = JSON.parse(temp);
		}
		catch (err){
			throw("xchat_protocol packet body format error.");
			return;
		}

		
		if ('sessionid' in packet_object)
		packet_object['uid'] = packet_object['sessionid'];

		switch (this.packet_para){
			case PACKET_LOGIN_ACK:
				if (packet_object['loginack'] == 0){
					this.Closed_By_Server = 1;
				}
				else{
					this.logined = true;
					if (packet_object['passport']){
						this.passport = packet_object['passport'];
					}
				}
				message_type = 'MSG_LOGIN_ACK';
				break;
			case PACKET_REENTER:
				this.logined = false;
				this.Closed_By_Server = 1;
				message_type = 'MSG_REENTER';
				break;
			case PACKET_ROOM_REINIT:
				message_type = 'MSG_ROOM_REINIT';
				break;
			case PACKET_SESSION_PARAM:
				this.SessionID = packet_object['sessionid'];
				message_type = 'MSG_SESSION_PARAM';
				break;
			case PACKET_SOMEBODY_IN:
				packet_object['in_out_hint'] = this.member_in_out_hint;
				if (this.member_in_out_hint==0){
					if (this.SessionID == packet_object['sessionid']){
						this.member_in_out_hint = 1;
					}
				}
				message_type = 'MSG_SOMEBODY_IN';
				break;
			case PACKET_SOMEBODY_OUT:
				packet_object['in_out_hint'] = this.member_in_out_hint;
				message_type = 'MSG_SOMEBODY_OUT';
				break;
			case PACKET_SOMEBODY_CHANGELEVEL:
				if (this.SessionID == packet_object['sessionid']){
					packet_object['self'] = 1;
				}
				message_type = 'MSG_SOMEBODY_CHANGELEVEL';
				break;
			case PACKET_SOMEBODY_CHANGEAPPDATA:
				if (this.SessionID == packet_object['sessionid']){
					packet_object['self'] = 1;
				}
				message_type = 'MSG_SOMEBODY_CHANGEAPPDATA';
				break;
			case PACKET_SOMEBODY_CHATENABLE:
				if (this.SessionID == packet_object['sessionid']){
					packet_object['self'] = 1;
				}
				message_type = 'MSG_SOMEBODY_CHATENABLE';
				break;
			case PACKET_KICKOUT:
				if (this.SessionID == packet_object['sessionid']){
					packet_object['self'] = 1;
					this.Closed_By_Server = 1;
				}
				message_type = 'MSG_KICKOUT';
				break;
			case PACKET_ROOMCLEAR:
				this.Closed_By_Server = 1;
				message_type = 'PACKET_ROOMCLEAR';
				break;
			case PACKET_ROOMHOT:
				message_type = 'MSG_ROOMHOT';
				break;
			case PACKET_CHAT:
				message_type = 'MSG_MESSAGE';
				break;
			case PACKET_TOKEN_SETTING:
				message_type = 'MSG_TOKEN_SETTING';
				break;
			case PACKET_TOKEN_TIMER:
				message_type = 'MSG_TOKEN_TIMER';
				break;	
			case PACKET_TOKEN_INFO:
				message_type = 'MSG_TOKEN_INFO';
				break;
			case PACKET_TOKEN_OP:
				message_type = 'MSG_TOKEN_REQUEST';
				if (packet_object['tokenop']==2){
					packet_object['type'] = 1;
				}
				else{
					packet_object['type'] = 0;
				}
				break;
			default :
				return;
		}
		if (xchat_swf_message){
			xchat_swf_message(message_type,packet_object,xmessager);
		}
	},

	Build_BA : function(para,Obj){
		if (Obj == null){
			var ba = [];
			push16(ba,0);
			push8(ba,1);
			push8(ba,para);
			return ba;
		}
		else{
			var s = JSON.stringify(Obj);
			
			var ba = [];
			push16(ba,s.length)
			push8(ba,1);
			push8(ba,para);
			pushStr(ba,s);
			return ba;
		}
	},

	packet_heartbeat : function(){
		return this.Build_BA(PACKET_HEARTBEAT,null);
	},
	
	packet_login : function(RoomID,UID,Level,appdata,token){
		var Obj = {};
		Obj['protocolversion'] = 257;//0x101;
		Obj['roomid'] = RoomID;
		Obj['roompara'] = 'RoomPara';
		Obj['gid'] = UID;
		Obj['level'] = Level;
		Obj['appdata'] = appdata;
		Obj['token'] = token;
		Obj['device'] = 1;

		if (this.passport !== '0'){
			Obj['passport'] = this.passport;
		}
			
		return this.Build_BA(PACKET_LOGIN,Obj);
	},
	
	packet_logout : function(){
		return this.Build_BA(PACKET_LOGOUT,null);
	}
};
	
export var xchat_ws = {
	wb_param:null,
	ws:null,
	heartbeat_ref:null,
	error_count:0,
	xmessager:null,
	publicChat:null,
	privateChat:null,
	init : function(wb_param,chatMode){
		//console.log(wb_param);
		
		xchat_protocol.passport = '0';

		xchat_ws.wb_param = wb_param;
		xchat_ws.error_count = 0;

		console.log(">> connect");
		if ((!xchat_ws.wb_param.ip) || (!xchat_ws.wb_param.port)) {
			console.log("must set ip and port");
			throw("websocket must set ip and port!");
		}

		if (xchat_ws.ws) {
			xchat_ws.ws.close();
		}

		var scheme = "ws://";
		var uri;

		uri = scheme + xchat_ws.wb_param.ip + ":" + xchat_ws.wb_param.port + "/websockify";
		console.log("connecting to " + uri);
		xchat_ws.ws = new Websock();
		xchat_ws.ws.open(uri);
		
		if (xchat_ws.heartbeat_ref == null){
			xchat_ws.heartbeat_ref = setInterval(xchat_ws.heartbeat, 1000*15)
		}
		let {uid,room_id,level,nickname,chatdisable} = wb_param
		//当前的自己
		xchat_ws.xmessager = new xMessager(uid,room_id,level,nickname,chatdisable,wb_param.chatShow)
		store.dispatch("setXmessager",xchat_ws.xmessager)
		if(wb_param && wb_param.chatShow){
			//公聊
			xchat_ws.publicChat = new ChatDisplay(document.getElementById("content_pub"),xchat_ws.xmessager,chatMode)
			//私聊
			xchat_ws.privateChat = new ChatDisplay(document.getElementById("content_prv"),xchat_ws.xmessager,chatMode)
		}
		xchat_ws.ws.on('message', ()=>{
			xchat_ws.do_recv(this.xmessager)
		});
		
		xchat_ws.ws.on('open', xchat_ws.do_open);
		
		xchat_ws.ws.on('close', xchat_ws.do_error);
		
		//xchat_ws.ws.on('error', xchat_ws.do_error);
		
		return true;
	},

	reconnect : function() {
		console.log('reconnect. ' + Date.now()/1000);

		var scheme = "ws://";
		var uri;

		uri = scheme + xchat_ws.wb_param.ip + ":" + xchat_ws.wb_param.port + "/websockify";
		console.log("reconnecting to " + uri);
		xchat_ws.ws = new Websock();
		xchat_ws.ws.open(uri);
		xchat_ws.xmessager = new xMessager(xchat_ws.wb_param)
		xchat_ws.ws.on('message', ()=>{
			xchat_ws.do_recv(this.xmessager)
		});
		
		xchat_ws.ws.on('open', xchat_ws.do_open);
		
		xchat_ws.ws.on('close', xchat_ws.do_error);
		
		//xchat_ws.ws.on('error', xchat_ws.do_error);
	},

	do_open : function(e) {
		console.log(">> WebSockets.onopen");

		xchat_ws.error_count = 0;
		//send login packet
		var login_timer = setInterval(function(){
			if(xchat_ws.ws.get_state() == 1){
				xchat_ws.ws.send(xchat_protocol.packet_login(xchat_ws.wb_param.room_id,xchat_ws.wb_param.uid,xchat_ws.wb_param.level,xchat_ws.wb_param.appdata,xchat_ws.wb_param.token));
				clearInterval(login_timer);
			}
		},1000);
	},

	do_error : function(e) {
		console.log(">> WebSockets.error.event");
		console.log(e);
		xchat_protocol.logined = false;
		xchat_ws.error_count += 1;
		if (xchat_ws.error_count>5){
			xchat_swf_error('WebSocket Error.',xchat_ws.xmessager);
			return;
		}
		if (!xchat_protocol.Closed_By_Server && xchat_swf_error !== 'undefined'){
			if (xchat_protocol.passport !== '0'){
				console.log('do_error. ' + Date.now()/1000);
				setTimeout(xchat_ws.reconnect,3000);
			}
			else{
				xchat_swf_error('WebSocket Error.',xchat_ws.xmessager);
			}
		}
	},

	heartbeat : function() {
		/*
		console.log(">> WebSockets.heartbeat");
		console.log(xchat_ws.ws);
		console.log(xchat_protocol.logined);
		*/
		if (xchat_ws.ws && xchat_ws.ws.get_state() == 1 && xchat_protocol.logined){
			xchat_ws.ws.send(xchat_protocol.packet_heartbeat());
			//console.log(">> WebSockets.heartbeat 111");
		}
	},
		
	logout : function(){
		if (xchat_ws.ws) {
			xchat_ws.ws.on('close', function(){});
			xchat_ws.ws.send(xchat_protocol.packet_logout());
			xchat_ws.ws.close();
		}
	},
	
	do_recv : function(xmessager){
		//var arr = ws.rQshiftBytes(ws.rQlen());
		while(1){
			if (xchat_protocol.packet_fetch_state == 0){
				if(xchat_ws.ws.rQlen() >= 4){
					xchat_protocol.packet_header = xchat_ws.ws.rQshiftBytes(4);
					xchat_protocol.parse_header();
					xchat_protocol.packet_fetch_state = 1;
				}
				else{
					break;
				}
			}
			else{
				if (xchat_ws.ws.rQlen() >= xchat_protocol.packet_body_length){
					xchat_protocol.packet_body = xchat_ws.ws.rQshiftBytes(xchat_protocol.packet_body_length);
					
					xchat_protocol.packet_fetch_state = 0;
					xchat_protocol.process_packet(xmessager);
				}
				else{
					break;
				}
			}
		}
	},
};